package ACEbrickBreaker;

/**
 * <p>Title: ControlPanel</p>
 * <p>Description: ControlPanel
 *       contains the action events for the game controls (restart, pause, help, view high scores).</p>
 * @author Caitlin Finn
 * @email caitlin.finn@my.uwrf.edu
 * @author Erin McNeil
 * @email erin.mcneil@my.uwrf.edu
 * @author Andrew Juranek
 * @email andrew.juranek@my.uwrf.edu
 * @date December 10th 2012
 */
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.text.DecimalFormat;
import java.text.NumberFormat;

import javax.swing.JButton;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.Timer;

public class ControlPanel extends JPanel {

	/**
     * 
     */
	private static final long serialVersionUID = 1L;
	// declare buttons & button handler
	private final JButton restart, pause, help, highScores;
	ButtonHandler action;

	// declare key listener
	DirectionListener direction;

	// declare panels
	private final TextPanel text;
	private final ImagePanel image;

	// declare bricks array, ball, paddle
	private final Brick[] bricks;
	private final Ball ball;
	private final Paddle paddle;

	// declare number formatter to display time
	NumberFormat formatter;

	// declare timer, timer handler, time delay
	Timer mainTimer;
	TimerHandler timer;
	final int TIMER_DELAY = 10;

	// declare time, score, lives
	int time, timeDisplay, score, count, lives = 3;

	/**
	 * constructor takes in copies of the TextfieldPanel and ImagePanel as well
	 * as copies of the brick array, ball, & paddle
	 * 
	 * @param text
	 * @param image
	 * @param bricks
	 * @param ball
	 * @param paddle
	 */

	public ControlPanel(TextPanel text, ImagePanel image, Brick[] bricks,
			Ball ball, Paddle paddle) {

		// instantiating panels and objects
		this.bricks = bricks;
		this.ball = ball;
		this.paddle = paddle;
		this.text = text;
		this.image = image;

		// instantiate action listeners
		action = new ButtonHandler();
		direction = new DirectionListener();
		timer = new TimerHandler();

		// instantiate formatter for time
		formatter = new DecimalFormat("00");

		// create timer
		mainTimer = new Timer(TIMER_DELAY, timer);
		time = 0;
		timeDisplay = 0;

		// add key listener
		image.addKeyListener(direction);
		image.requestFocusInWindow();

		// create buttons and add button listeners
		restart = new JButton("RESTART");
		restart.addActionListener(action);
		pause = new JButton("PAUSE/RESUME");
		pause.addActionListener(action);
		help = new JButton("HELP");
		help.addActionListener(action);
		highScores = new JButton("View High Scores");
		highScores.addActionListener(action);

		// setting up panel with grid layout
		this.setLayout(new GridLayout(4, 1));
		this.add(highScores);
		this.add(help);
		this.add(restart);
		this.add(pause);

	}

	// button listener for restart and pause buttons
	class ButtonHandler implements ActionListener {

		/*
		 * (non-Javadoc)
		 * 
		 * @see
		 * java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent
		 * )
		 */
		@Override
		public void actionPerformed(ActionEvent e) {
			if (e.getActionCommand().equals("View High Scores")) {
				new ReadXMLscoresFile();
			} else if (e.getActionCommand().equals("RESTART")) {

				// resets every brick to being not hit
				for (Brick i : bricks) {
					i.setHit(false);
				}

				// resets every textfield and variable back to 0
				lives = 3;
				score = 0;
				time = 0;
				timeDisplay = 0;
				text.setTime("" + formatter.format(timeDisplay / 60) + ":"
						+ formatter.format(timeDisplay % 60));
				text.setLives("" + lives);
				text.setScore("" + score);

				// resets position of ball and paddle to initial position
				ball.setX(400);
				ball.setY(498);
				ball.setXVelocity(0);
				ball.setYVelocity(0);
				paddle.setX(335);
				paddle.setY(520);

				// stops timer resets up image panel
				mainTimer.stop();
				image.requestFocusInWindow();
				image.updateBoard();
			} else if (e.getActionCommand().equals("PAUSE/RESUME")) {

				// stops timer
				if (mainTimer.isRunning()) {
					mainTimer.stop();
					image.requestFocusInWindow();
				} else {
					mainTimer.start();
					image.requestFocusInWindow();
				}
			} else if (e.getActionCommand().equals("HELP")) {
				JOptionPane
						.showMessageDialog(
								null,
								"Press space bar to start the game.\n Hit the ball with your paddle so that the ball destroys as \n many bricks as possible.  The ball will speed up \n as the color levels disappear.",

								"INSTRUCTIONS", JOptionPane.INFORMATION_MESSAGE);
			}
		}
	}

	class DirectionListener implements KeyListener {

		/*
		 * (non-Javadoc)
		 * 
		 * @see java.awt.event.KeyListener#keyPressed(java.awt.event.KeyEvent)
		 */
		@Override
		public void keyPressed(KeyEvent event) {
			switch (event.getKeyCode()) {
			case KeyEvent.VK_LEFT:
				// sets paddle left boundary and sets position of paddle
				if (paddle.getX() > 0 && mainTimer.isRunning()) {
					paddle.setX(paddle.getX() - 16);
				}
				break;
			case KeyEvent.VK_RIGHT:
				// sets paddle right boundary and sets position of paddle
				if (paddle.getX() + 150 < 850 && mainTimer.isRunning()) {

					paddle.setX(paddle.getX() + 16);
				}
				break;
			case KeyEvent.VK_SPACE:
				// starts timer and releases the ball
				mainTimer.start();
				if (ball.getX() == ACEgameGUI.ballX
						&& ball.getY() == ACEgameGUI.ballY) {
					ball.setYVelocity(-4);
					ball.setXVelocity(-4);
				}
				break;
			}
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see java.awt.event.KeyListener#keyTyped(java.awt.event.KeyEvent)
		 */
		@Override
		public void keyTyped(KeyEvent event) {
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see java.awt.event.KeyListener#keyReleased(java.awt.event.KeyEvent)
		 */
		@Override
		public void keyReleased(KeyEvent event) {
		}
	}

	class TimerHandler implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent e) {

			// time is increased once timer begins
			time++;
			// used for displaying time
			if (time % 10 == 0) {
				timeDisplay++;
			}

			// sets text fields
			text.setTime("" + formatter.format(timeDisplay / 60) + ":"
					+ formatter.format(timeDisplay % 60));
			text.setScore("" + score);
			text.setLives("" + lives);

			// checks if ball has hit anything and sets velocities; repaint
			checkContact();
			ball.setX(ball.getX() + ball.getXVelocity());
			ball.setY(ball.getY() + ball.getYVelocity());
			image.updateBoard();
		}

	}

	/**
	 * checkContact() Checks if the ball is in contact with the paddle or a
	 * brick
	 */

	private void checkContact() {
		// sets boundaries for ball in the horizontal direction
		if (ball.getX() + 20 >= 800 || ball.getX() <= 0) {
			ball.setXVelocity(-1 * ball.getXVelocity());
		}
		// sets boundary for upper wall in vertical direction
		if (ball.getY() < 0) {
			ball.setYVelocity(-1 * ball.getYVelocity());
		}
		// checks if ball touches paddle; if so allows ball to go in reverse y
		// velocity
		if (ball.getY() + 20 >= paddle.getY()
				&& (ball.getX() >= paddle.getX() && ball.getX() <= (paddle
						.getX() + 150))) {
			if (ball.getY() + 20 <= paddle.getY() + 9) {
				ball.setYVelocity(-1 * ball.getYVelocity());
			}
		}

		// if the ball drops below the paddle loses a life and resets to initial
		// position
		if (ball.getY() + 20 > paddle.getY() + 20) {
			lives--;
			text.setLives("" + lives);
			mainTimer.stop();
			ball.setX(ACEgameGUI.ballX);
			ball.setY(ACEgameGUI.ballY);
			ball.setXVelocity(0);
			ball.setYVelocity(0);
			paddle.setX(ACEgameGUI.paddleX);
			paddle.setY(ACEgameGUI.paddleY);
		}

		// checks if ball hits a brick; if so resets x velocity and sets brick
		// to being hit; update score
		for (Brick i : bricks) {
			if (ball.getX() + 20 >= i.getX() && ball.getX() <= i.getX() + 100) {
				if (ball.getY() + 20 >= i.getY()
						&& ball.getY() <= i.getY() + 45) {
					if (!i.isHit()) {
						if (ball.getX() + 20 - ball.getXVelocity() <= i.getX()
								|| ball.getX() - ball.getXVelocity() >= i
										.getX() + 100) {
							ball.setXVelocity(-1 * ball.getXVelocity());
							i.setHit(true);
							if (i.colorCode == 5)
								score += 100;
							else
								score += 50;
						} else {
							ball.setYVelocity(-1 * ball.getYVelocity());
							i.setHit(true);
							if (i.colorCode == 5)
								score += 100;
							else
								score += 50;
						}
					}
				}
			}
			if (i.isHit()) {
				count++;
			}
		}

		// if all bricks have been hit then stop the timer
		if (count == bricks.length) {
			mainTimer.stop();
			WriteXMLscoresFile xmlFile = new WriteXMLscoresFile(
					text.getPlayerName(), Integer.toString(score),
					("" + formatter.format(timeDisplay / 60) + ":" + formatter
							.format(timeDisplay % 60)));
		}
		// if loses all lives resets everything
		if (lives == 0) {
			WriteXMLscoresFile xmlFile = new WriteXMLscoresFile(
					text.getPlayerName(), Integer.toString(score),
					("" + formatter.format(timeDisplay / 60) + ":" + formatter
							.format(timeDisplay % 60)));
			JOptionPane.showMessageDialog(null, "GAME OVER.", "GAME OVER.",
					JOptionPane.PLAIN_MESSAGE);
			mainTimer.stop();
			for (Brick i : bricks) {
				i.setHit(false);
			}
			lives = 3;
			time = 0;
			text.setLives("" + lives);
			score = 0;
			timeDisplay = 0;

			text.setTime("" + formatter.format(timeDisplay / 60) + ":"
					+ formatter.format(timeDisplay % 60));
			text.setScore("" + score);

			ball.setX(ACEgameGUI.ballX);
			ball.setY(ACEgameGUI.ballY);
			ball.setXVelocity(0);
			ball.setYVelocity(0);
			paddle.setX(ACEgameGUI.paddleX);
			paddle.setY(ACEgameGUI.paddleY);

		}

		count = 0;

	}
}